/***************************************************************************
      File Name:  FileHelpers.cs
   File Created:  Wednesday, June 13th 2007
      Copyright:  (C) 2007 by Darko Matesic
          Email:  darko.matesic@yahoo.com
 ***************************************************************************/

using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Windows.Forms;

namespace CallerID.Helpers
{
    public class FileHelpers
    {

        /// <summary>
        /// Checks if specified file name is valid (contains valid characters).
        /// </summary>
        public static bool IsFileNameValid(string fileName)
        {
            if(fileName != null && fileName.Length > 0) {
                return fileName.IndexOfAny(System.IO.Path.GetInvalidFileNameChars()) == -1;
            }
            return false;
        }

        /// <summary>
        /// Appends specified extension to specified file name if file name does not end with specified extension.
        /// </summary>
        public static string AppendExtension(string fileName, string extension)
        {

            if(fileName != null && fileName.Length > 0) {
                if(extension != null && extension.Length > 0 && extension != ".") {
                    if(extension.StartsWith(".") == false) extension = "." + extension;
                    if(fileName.ToLower().EndsWith(extension.ToLower()) == false) fileName += extension;
                }
                return fileName;
            }
            return "";
        }

        /// <summary>
        /// Returns file name (with extension) part from full path.
        /// </summary>
        public static string GetFileName(string fullPath)
        {
            try { 
                return System.IO.Path.GetFileName(fullPath); 
            } catch { }
            return "";
        }

        /// <summary>
        /// Returns file name (without extension) from full path.
        /// </summary>
        public static string GetFileNameWithoutExtension(string fullPath)
        {
            try { 
                return System.IO.Path.GetFileNameWithoutExtension(fullPath);
            } catch { }
            return "";
        }

        /// <summary>
        /// Returns file name extension from full path.
        /// </summary>
        public static string GetExtension(string fullPath)
        {
            try {
                return System.IO.Path.GetExtension(fullPath);
            } catch { }
            return "";
        }

        /// <summary>
        /// Reads text file and returns data in output parameter.
        /// </summary>
        /// <param name="fileName">Name of a file to read</param>
        /// <param name="text">string that will hold data read from a file</param>
        /// <returns>True if file was successfuly read; otherwise, false</returns>
        public static bool ReadTextFile(string fileName, ref string text)
        {
            if(fileName == null || fileName.Length == 0) return false;
            if(!File.Exists(fileName)) return false;
            try {
                text = File.ReadAllText(fileName);
                return true;
            } catch { }
            return false;
        }

        /// <summary>
        /// Reads text file and returns string that contains text from file.
        /// </summary>
        /// <param name="fileName">Name of a file to read</param>
        /// <param name="text">string that will hold data read from a file</param>
        /// <returns>True if file was successfuly read; otherwise, false</returns>
        public static string ReadTextFile(string fileName)
        {
            if(fileName != null || fileName.Length >= 0) {
                try {
                    return File.ReadAllText(fileName);
                } catch { }
            }
            return "";
        }

        /// <summary>
        /// Writes a string to a file.
        /// </summary>
        /// <param name="fileName">Name of a file to save</param>
        /// <param name="text">string to save</param>
        /// <param name="unicode">If true, save text file as unicode</param>
        /// <param name="backup">If true, make backup before preforming saving</param>
        /// <returns>True if file was successfuly saved; otherwise, False</returns>
        public static bool SaveTextFile(string fileName, string text, bool unicode, bool backup)
        {
            if(fileName == null || fileName.Length == 0) return false;
            if(backup && System.IO.File.Exists(fileName)) {
                string backupFileName = fileName + ".backup";
                try { if(System.IO.File.Exists(backupFileName)) System.IO.File.Delete(backupFileName); } catch { }
                try { System.IO.File.Move(fileName, backupFileName); } catch { }
            }
            try {
                if(unicode)
                    File.WriteAllText(fileName, text, Encoding.Unicode);
                else
                    File.WriteAllText(fileName, text, Encoding.UTF8);
                return true;
            } catch { }
            return false;
        }

        /// <summary>
        /// Writes a string to a file.
        /// </summary>
        /// <param name="fileName">Name of a file to save</param>
        /// <param name="text">string to save</param>
        /// <returns>True if file was successfuly saved; otherwise, False</returns>
        public static bool SaveTextFile(string fileName, string text)
        {
            return SaveTextFile(fileName, text, false, false);
        }

        /// <summary>
        /// Return file version in string format
        /// </summary>
        public static string FileVersion(string fileName)
        {
            System.Diagnostics.FileVersionInfo fileVersionInfo = null;
            try { fileVersionInfo = System.Diagnostics.FileVersionInfo.GetVersionInfo(fileName); } catch { }
            if(fileVersionInfo == null) return "";
            return fileVersionInfo.ProductVersion;
        }

        /// <summary>
        /// Returns file version in integer format
        /// </summary>
        public static int FileVersionInteger(string fileName)
        {
            string[] version = FileVersion(fileName).Split(new char[] { '.' }, StringSplitOptions.RemoveEmptyEntries);
            int ver = 0;
            if(version.Length >= 1) ver += ConversionHelpers.StringToInteger(version[0], 0) * 1000000000;
            if(version.Length >= 2) ver += ConversionHelpers.StringToInteger(version[1], 0) * 1000000;
            if(version.Length >= 3) ver += ConversionHelpers.StringToInteger(version[2], 0) * 1000;
            if(version.Length >= 4) ver += ConversionHelpers.StringToInteger(version[3], 0);
            return ver;
        }

        /// <summary>
        /// Copy source file to destination and if destination already exists it makes destination backup
        /// </summary>
        public static bool CopyFile(string source, string destination, string destinationBackup)
        {
            string temp = destination + ".temp";
            try {
                if(System.IO.File.Exists(temp)) System.IO.File.Delete(temp);
                System.IO.File.Copy(source, temp);
                if(destinationBackup != null && destinationBackup.Length > 0 && System.IO.File.Exists(destination)) {
                    if(System.IO.File.Exists(destinationBackup)) System.IO.File.Delete(destinationBackup);
                    System.IO.File.Move(destination, destinationBackup);
                }
                System.IO.File.Move(temp, destination);
                return true;
            } catch { }
            return false;
        }

        /// <summary>
        /// Copy source file to destination and if destination already exists it overwrites it
        /// </summary>
        public static bool CopyFileWithOverwrite(string source, string destination)
        {
            try {
                try {
                    if(System.IO.File.Exists(destination)) {
                        System.IO.File.SetAttributes(destination, FileAttributes.Normal);
                    }
                } catch { }
                System.IO.File.Copy(source, destination, true);
                return true;
            } catch { }
            return false;
        }

        /// <summary>
        /// Copy source file over destination file, if copyIfNewer is specified then only if source is of newer date copy is performed
        /// </summary>
        public static bool CopyFile(string source, string destination, bool copyIfNewer)
        {
            try {
                if(CheckCopyFile(source, destination, copyIfNewer) == false) return false;
                if(System.IO.File.Exists(destination))
                    System.IO.File.Delete(destination);
                else {
                    string destinationDirectory = System.IO.Path.GetDirectoryName(destination);
                    if(System.IO.Directory.Exists(destinationDirectory) == false) System.IO.Directory.CreateDirectory(destinationDirectory);
                }
                System.IO.File.Copy(source, destination, true);
                return true;
            } catch { }
            return false;
        }

        /// <summary>
        /// Returns true if method CopyFile would perform file copy
        /// </summary>
        public static bool CheckCopyFile(string source, string destination, bool copyIfNewer)
        {
            try {
                bool source_exists = System.IO.File.Exists(source);
                bool destination_exists = System.IO.File.Exists(destination);
                if(source_exists && destination_exists == false) return true;
                if(source_exists && destination_exists) {
                    try {
                        FileInfo source_info = new System.IO.FileInfo(source);
                        FileInfo destination_info = new System.IO.FileInfo(destination);
                        if(source_info.Length != destination_info.Length) return true;
                    } catch { }
                    if(copyIfNewer) {
                        try {
                            DateTime timeSource = System.IO.File.GetLastWriteTime(source);
                            DateTime timeDestination = System.IO.File.GetLastWriteTime(destination);
                            if(timeSource.CompareTo(timeDestination) > 0) return true;
                        } catch { }
                    }
                }
            } catch { }
            return false;
        }


        /// <summary>
        /// Returns size of file. If file does not exist it returns -1.
        /// </summary>
        /// <param name="fileName">name of file to return it's size.</param>
        /// <returns>Size of file; -1 if file does not exist.</returns>
        public static long FileSize(string fileName)
        {
            try {
                if(System.IO.File.Exists(fileName) == false) return -1;
                System.IO.FileInfo info = new System.IO.FileInfo(fileName);
                return info.Length;
            } catch { }
            return -1;
        }

        /// <summary>
        /// Sets new size for specified file, if file does not exist it creates new file with specified name and size.
        /// </summary>
        /// <param name="fileName">name of file to change it's size.</param>
        /// <param name="size">size of file to set</param>
        /// <param name="onlyIfLarger">if true size is set only if current file size is greater than specified size.</param>
        /// <returns>true when operation is successful; otherwise, false</returns>
        public static bool SetFileSize(string fileName, long size, bool onlyIfLarger)
        {
            FileStream stream = null;
            try {
                if(size < 0) size = 0;
                stream = File.Open(fileName, FileMode.OpenOrCreate, FileAccess.Write);
                if(stream != null) {
                    if(!(onlyIfLarger && stream.Length <= size)) stream.SetLength(size);
                    stream.Close();
                    stream.Dispose();
                    return true;
                }
            } catch {
            } finally {
                if(stream != null) try { stream.Close(); stream.Dispose(); } catch { }
            }
            return false;
        }

    }
}
